Git Internals 读书笔记。
Git Object Types
Git
有四种对象类型,分别是Blob
、Tree
、Commit
和Tag
,都存储在对象数据库里,都是通过Zlib
压缩过的,使用SHA-1
值(内容的哈希值)来表示。
使用书上的例子:
Blob
在Git
中,文件的内容是作为Blob
进行存储的。
对于具有相同内容的不同文件,只存储一份。
Tree
Tree
就对应着目录。
tree
存储该目录下的目录和文件的信息(mode
,type
,name
,sha
)。
Commit
commit
对象指向一个tree
对象,然后额外保存了作者,提交者,提交信息和上次提交这些信息。
第一次提交
第二次提交
在第二次提交中,就有了parent
这一信息,指向上一次的提交对象。
Tag
Tag
对象指向一个特定的commit
对象,保存object
,type
,tag
,tagger
和message
信息。type
一般就是commit
,object
就是这个commit
的SHA-1
值。
Git Data Model
The Model
带颜色是不可变对象。
Example
目录文件如下
|-- init.rb
-- lib
| -- base
| -- base_include.rb
-- my_plugin.rb
第一次提交后,Git Model
如下
branch
指向最近的一次提交,HEAD
指向当前的branch
。
现在修改lib/base/base_include.rb
文件,然后提交,并创建一个tag
。
修改了文件,其父目录以及父目录的父目录直到最顶层目录的内容都被修改了,就会产生新的对象。对于没有改变的文件和目录则不会产生新对象。
现在修改init.rb
文件,然后提交。
由于只修改了init.rb
文件,其他的子目录并没有变化,所以就不会产生其他的新对象。如下图所示。
这样的一种模型,我们可以通过当前的HEAD
得到所有的历史文件。
Traversal
当进行checkout
的时候,通过查看.git/refs
目录下的branch
,tag
,remote
,将当前的working directory
的内容切换到指定的commit
的内容。
Branching and Merging
在Git
中,创建分支,切换分支是非常容易的,就是新建一个文件和写几个字符的事。
在这个例子中,创建一个experiment
分支,然后对master
和experiment
分支分别提交。现在就是下面这个样子。
将experiment
分支合并到master
分支后就像下面这样。
Remotes
远程分支的名字类似与这样origin/master
表示远程仓库origin
的master
分支。远程仓库的名字origin
是可以自定义的,不一定就是origin
。
下面表示有三个分支,两个远程仓库分支idea
和master
,一个本地分支。
对这三个分支进行合并,就成了下面这个样子。
Rebasing
在多人合作开发时,将别人的代码合并到自己本地时,就会产生下面所示的情况。
C2
,C4
,C5
这些并没有什么实质的内容,只是进行合并产生的提交。当有大量的这些提交后,我们的提交历史就会变得不清晰。这时,我们可以使用rebase
。
使用rebase
的效果和merge
的效果如下所示。
1是rebase
产生的提交历史。
2是merge
产生的提交历史。
rebase
只在本地分支上使用,不要在公共的分支上进行rebase
!